// 导入模块
import { _decorator, Component, Vec3, input, Input, EventKeyboard, KeyCode, Animation } from 'cc';
const { ccclass, property } = _decorator;

/**
 * 角色动画状态枚举
 */
enum AnimationState {
    /**
     * 待机状态
     */
    IDLE = 'idle',
    /**
     * 行走状态
     */
    WALK = 'walk',
    /**
     * 奔跑状态
     */
    RUN = 'run',
    /**
     * 跳跃状态
     */
    JUMP = 'jump',
}

/**
 * 玩家角色控制器，处理玩家输入和移动
 * 负责处理WASD键盘输入并控制角色移动
 */
@ccclass('Player')
export class Player extends Component {
    /**
     * 移动速度(单位：米/秒)
     */
    @property
    public moveSpeed: number = 5;

    /**
     * 跳跃高度
     */
    @property
    public jumpHeight: number = 2;

    /**
     * 重力加速度
     */
    @property
    public gravity: number = 9.8;

    /**
     * 闪避距离
     */
    @property
    public dodgeDistance: number = 3;

    /**
     * 闪避冷却时间(秒)
     */
    @property
    public dodgeCooldown: number = 1;

    /**
     * 动画组件引用
     */
    @property(Animation)
    public animationComponent: Animation | null = null;

    /**
     * 垂直速度(用于跳跃)
     */
    private _verticalVelocity: number = 0;

    /**
     * 是否在地面
     */
    private _isGrounded: boolean = true;

    /**
     * 闪避冷却计时器
     */
    private _dodgeCooldownTimer: number = 0;

    /**
     * 目标位置坐标
     */
    private _targetPosition: Vec3 = new Vec3();

    /**
     * 当前移动方向向量
     */
    private _moveDirection: Vec3 = new Vec3();

    /**
     * 是否按下W键
     */
    private _isWPressed: boolean = false;

    /**
     * 是否按下S键
     */
    private _isSPressed: boolean = false;

    /**
     * 是否按下A键
     */
    private _isAPressed: boolean = false;

    /**
     * 是否按下D键
     */
    private _isDPressed: boolean = false;

    /**
     * 当前动画状态
     */
    private _currentAnimationState: AnimationState = AnimationState.IDLE;

    /**
     * 组件加载时调用，注册键盘事件监听
     */
    protected onLoad(): void {
        input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
        input.on(Input.EventType.KEY_UP, this.onKeyUp, this);
    }

    /**
     * 组件销毁时调用，取消键盘事件监听
     */
    protected onDestroy(): void {
        input.off(Input.EventType.KEY_DOWN, this.onKeyDown, this);
        input.off(Input.EventType.KEY_UP, this.onKeyUp, this);
    }

    /**
     * 处理键盘按下事件
     * @param event 键盘事件对象
     */
    private onKeyDown(event: EventKeyboard): void {
        switch (event.keyCode) {
            case KeyCode.KEY_W:
                this._isWPressed = true;
                break;
            case KeyCode.KEY_S:
                this._isSPressed = true;
                break;
            case KeyCode.KEY_A:
                this._isAPressed = true;
                break;
            case KeyCode.KEY_D:
                this._isDPressed = true;
                break;
            case KeyCode.SPACE:
                this.jump();
                break;
            case KeyCode.SHIFT_LEFT:
            case KeyCode.SHIFT_RIGHT:
                this.dodge();
                break;
        }
        this.updateMoveDirection();
    }

    /**
     * 处理键盘释放事件
     * @param event 键盘事件对象
     */
    private onKeyUp(event: EventKeyboard): void {
        switch (event.keyCode) {
            case KeyCode.KEY_W:
                this._isWPressed = false;
                break;
            case KeyCode.KEY_S:
                this._isSPressed = false;
                break;
            case KeyCode.KEY_A:
                this._isAPressed = false;
                break;
            case KeyCode.KEY_D:
                this._isDPressed = false;
                break;
        }
        this.updateMoveDirection();
    }

    /**
     * 更新移动方向向量
     */
    private updateMoveDirection(): void {
        this._moveDirection.set(0, 0, 0);

        if (this._isWPressed) this._moveDirection.z -= 1;
        if (this._isSPressed) this._moveDirection.z += 1;
        if (this._isAPressed) this._moveDirection.x -= 1;
        if (this._isDPressed) this._moveDirection.x += 1;

        // 标准化方向向量
        if (this._moveDirection.length() > 0) {
            Vec3.normalize(this._moveDirection, this._moveDirection);
        }
    }

    /**
     * 每帧更新移动、跳跃和动画
     * @param dt 帧间隔时间(秒)
     */
    public update(dt: number): void {
        // 更新闪避冷却
        if (this._dodgeCooldownTimer > 0) {
            this._dodgeCooldownTimer -= dt;
        }

        // 处理跳跃物理
        if (!this._isGrounded) {
            this._verticalVelocity -= this.gravity * dt;
            const newPosition = this.node.position.clone();
            newPosition.y += this._verticalVelocity * dt;

            // 检测是否落地
            if (newPosition.y <= 0) {
                newPosition.y = 0;
                this._verticalVelocity = 0;
                this._isGrounded = true;
                this.playAnimation(AnimationState.IDLE);
            }
            this.node.setPosition(newPosition);
        }

        if (this._moveDirection.length() > 0) {
            // 计算移动向量
            const moveDelta = new Vec3(
                this._moveDirection.x * this.moveSpeed * dt,
                0,
                this._moveDirection.z * this.moveSpeed * dt,
            );

            // 更新位置
            Vec3.add(this.node.position, this.node.position, moveDelta);

            // 更新角色朝向
            if (this._moveDirection.z !== 0 || this._moveDirection.x !== 0) {
                const targetAngle =
                    (Math.atan2(this._moveDirection.x, this._moveDirection.z) * 180) / Math.PI;
                this.node.setRotationFromEuler(0, targetAngle, 0);
            }

            // 播放行走动画
            this.playAnimation(this._isGrounded ? AnimationState.WALK : AnimationState.JUMP);
        } else {
            // 播放待机动画
            this.playAnimation(this._isGrounded ? AnimationState.IDLE : AnimationState.JUMP);
        }
    }

    /**
     * 播放指定动画
     * @param state 动画状态
     */
    private playAnimation(state: AnimationState): void {
        if (this._currentAnimationState !== state && this.animationComponent) {
            this.animationComponent.play(state);
            this._currentAnimationState = state;
        }
    }

    /**
     * 初始化玩家位置和状态
     */
    public init(): void {
        this._targetPosition = this.node.position.clone();
        this._moveDirection.set(0, 0, 0);
        this._isWPressed = false;
        this._isSPressed = false;
        this._isAPressed = false;
        this._isDPressed = false;
    }

    /**
     * 执行跳跃
     */
    public jump(): void {
        if (this._isGrounded) {
            this._verticalVelocity = Math.sqrt(2 * this.gravity * this.jumpHeight);
            this._isGrounded = false;
            this.playAnimation(AnimationState.JUMP);
        }
    }

    /**
     * 执行闪避
     */
    public dodge(): void {
        if (this._isGrounded && this._dodgeCooldownTimer <= 0) {
            const dodgeDirection =
                this._moveDirection.length() > 0
                    ? this._moveDirection
                    : Vec3.FORWARD.clone().transformMat4(this.node.worldMatrix);

            Vec3.normalize(dodgeDirection, dodgeDirection);
            Vec3.multiplyScalar(dodgeDirection, dodgeDirection, this.dodgeDistance);

            this.node.position.add(dodgeDirection);
            this._dodgeCooldownTimer = this.dodgeCooldown;
        }
    }

    /**
     * 重置玩家到初始状态
     */
    public reset(): void {
        this.init();
    }
}
